import numpy as np
from Graph import Graph

G = Graph()
dist = G.dist

def path_length(path):
    length = 0
    for i in range(len(path) - 1):
        length += dist[path[i]][path[i+1]]
    return length

#selection
def selection(pop, scores, k = 3):
    #first random selection
    selection_ix = np.random.randint(len(pop))
    for ix in np.random.randint(0,len(pop),k-1):
        #check if better
        if scores[ix] < scores[selection_ix]:
            selection_ix = ix
    return pop[selection_ix]
#crossever two parents to create two children
def crossover(p1, p2, r_cross):
    c1, c2 = p1.copy(), p2.copy()
    if np.random.rand() < r_cross:
        pt = np.random.randint(1, len(p1) -2)
        #perform crossover
        c1 = p1[:pt] + p2[pt:]
        c2 = p2[:pt] + p1[pt:]
    return [c1, c2]
    
def mutation(path, r_mut):
    for i in range(len(path)):
        for i in range(len(path)):
            path[i] = np.random.randint(0, len(path))


def gentic_algorithm(path_length, n_node, n_iter, n_pop, r_cross, r_mut):
    #pop = [[np.random.randint(0, n_node) for j in range(n_node)] for j in range(n_pop)]
    best, best_eval = 0, path_length(pop[0])
    #enumerate generations
    for gen in range(n_iter):
        #evaluate all path length in the population
        paths_length = [path_length(path) for path in pop]
        #check for new best solution
        for i in range(n_pop):
            if paths_length[i] < best_eval:
                best, best_eval = pop[i], paths_length[i]
                print(">", gen, "new best f", pop[i], "=", paths_length[i])
        '''
        #select parents
        selected = [selection(pop, paths_length) for i in range(n_pop)]
        
        #create the next generation
        children = list()

        for i in range(0,n_pop-1, 2):
            #get selected parents in pairs
            p1, p2 = selected[i], selected[i+1]
            #crossover and mutation
            for c in crossover(p1, p2, r_cross):
                #mutation
                mutation(c, r_mut)
                children.append(c)
        #replace population
        '''
    return [best, best_eval]

pop = None

with open("permutation.txt", encoding = 'utf-8') as f:
    pop = np.loadtxt(f, int,delimiter = ' ')

print(pop)

gentic_algorithm(path_length, 5, 1, len(pop), 0.3, 0.1)
